package com.jiazaibendi.lottery.service.impl;

import com.jiazaibendi.lottery.common.CommonConstant;
import com.jiazaibendi.lottery.dao.domain.*;
import com.jiazaibendi.lottery.dao.mapper.UserInfoMapper;
import com.jiazaibendi.lottery.dao.mapper.WinRecordExtMapper;
import com.jiazaibendi.lottery.dao.mapper.WinRecordMapper;
import com.jiazaibendi.lottery.service.RecordService;
import com.jiazaibendi.lottery.service.RedisService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

import static java.util.stream.Collectors.toList;

/**
 * description
 *
 * @author echo_kai
 * @version 1.0
 * @date 2021/08/07
 */
@Service
@Slf4j
public class RecordServiceImpl implements RecordService {

    @Resource
    private WinRecordMapper winRecordMapper;

    @Resource
    private UserInfoMapper userInfoMapper;

    @Resource
    private WinRecordExtMapper winRecordExtMapper;

    @Resource
    private RedisService redisService;

    public Map<Long, Long> hourFlow = new ConcurrentHashMap<>();

    @Override
    public Long gainAnyPrize(long userId, long schemeId, long prizeType) {
        hourFlow.put(schemeId, queryHourFlow(schemeId) + 1);
        if (prizeType == 0) return 0L;
        UserInfo userInfo = userInfoMapper.selectByPrimaryKey(userId);
        WinRecord record = new WinRecord();
        record.setPrizeId(prizeType);
        record.setSchemeId(schemeId);
        record.setTelephone(userInfo.getTelephone());
        record.setUserId(userId);
        record.setWinTime(new Date());
        winRecordMapper.insert(record);
        return record.getId();
    }

    @Override
    public List<WinRecord> queryPrizeRecord(long schemeId) {
        WinRecordExample example = new WinRecordExample();
        example.createCriteria().andSchemeIdEqualTo(schemeId);
        example.setOrderByClause("win_time desc");
        List<WinRecord> winRecords = winRecordMapper.selectByExample(example);
        return winRecords.stream().limit(5).collect(toList());
    }

    @Override
    public long queryAllJoinPeopleNumber(long schemeId) {
        return ((Integer) redisService.get(CommonConstant.SCHEMA_All_JOIN_NUMBER + ":" + schemeId)).longValue();
    }

    @Override
    public long queryGainPrizePeopleNumber(long schemeId) {
        return winRecordExtMapper.queryGainPrizePeopleNumber(schemeId);
    }

    @Override
    public void updateWinRecord(long recordId, long telephone, String name) {
        WinRecord winRecord = winRecordMapper.selectByPrimaryKey(recordId);
        winRecord.setTelephone(telephone);
        winRecord.setName(name);
        winRecordMapper.updateByPrimaryKey(winRecord);
    }

    @Override
    public long queryHourFlow(long schemeId) {
        if (hourFlow.containsKey(schemeId)) {
            return hourFlow.get(schemeId);
        }
        hourFlow.put(schemeId, 0L);
        return 0;
    }

    @Override
    public void clearHourFlow(long schemeId) {
        hourFlow.put(schemeId, 0L);
    }

    @Override
    public boolean queryHaveEntity(long schemeId, long userId, long prizeId) {
        if (prizeId > 5 ) return false;
        WinRecordExample example = new WinRecordExample();
        example.createCriteria().andPrizeIdBetween(1L,6L).andUserIdEqualTo(userId).andSchemeIdEqualTo(schemeId);
        return !CollectionUtils.isEmpty(winRecordMapper.selectByExample(example));
    }

    @Override
    public boolean queryHaveEnvelope(long schemeId, long userId, long prizeId) {
        if (prizeId < 5 || prizeId>10) return false;
        WinRecordExample example = new WinRecordExample();
        example.createCriteria().andUserIdEqualTo(userId).andSchemeIdEqualTo(schemeId)
                .andWinTimeGreaterThanOrEqualTo(Date.from(LocalDate.now().atStartOfDay(ZoneId.systemDefault()).toInstant()))
                .andPrizeIdBetween(6L,10L);
        return !CollectionUtils.isEmpty(winRecordMapper.selectByExample(example));
    }

    @Override
    public boolean queryHaveCoupon(long schemeId, long userId, long prizeId) {
        if (prizeId < 11) return false;
        WinRecordExample example = new WinRecordExample();
        example.createCriteria().andPrizeIdBetween(11L,13L).andUserIdEqualTo(userId).andSchemeIdEqualTo(schemeId);
        return !CollectionUtils.isEmpty(winRecordMapper.selectByExample(example));
    }

    @Override
    public List<WinRecordVo> queryMyPrizes(long schemeId, long userId) {
        return winRecordExtMapper.selectPrizeList(userId,schemeId);
    }

    @Override
    public long getUserIdByTelephone(long telephone) {
        UserInfoExample example = new UserInfoExample();
        example.createCriteria().andTelephoneEqualTo(telephone);
        List<UserInfo> userInfos = userInfoMapper.selectByExample(example);
        if (CollectionUtils.isEmpty(userInfos)) {
            UserInfo userInfo = new UserInfo();
            userInfo.setTelephone(telephone);
            userInfoMapper.insert(userInfo);
            return userInfo.getId();
        }
        return userInfos.get(0).getId();
    }

    @Override
    public UserInfo getUserByOpenId(String openid) {
        UserInfoExample example = new UserInfoExample();
        example.createCriteria().andOpenidEqualTo(openid);
        List<UserInfo> userInfos = userInfoMapper.selectByExample(example);
        if(userInfos.isEmpty()){
            return null;
        }
        return userInfos.get(0);
    }

    @Override
    public void insertUser(UserInfo userInfo) {
        if(userInfoMapper.insertSelective(userInfo) <= 0){
         throw new RuntimeException("用户创建失败");
        }

    }

    @Override
    public void clearAllJoinPeopleNumber(long schemeId) {
        redisService.set(CommonConstant.SCHEMA_All_JOIN_NUMBER + ":" + schemeId, 0);
    }

    @Override
    public void addAllJoinPeopleNumber(long schemeId) {
        redisService.incr(CommonConstant.SCHEMA_All_JOIN_NUMBER + ":" + schemeId, 1);
    }
}
